
import { TGALogger } from './tga';
export { ALiSLSParams } from "./taobao"
export { TGAParams } from "./tga"
export { LogKitParams } from './logkit';
import { TaoBaoLogger, ALiSLSParams } from './taobao';
import { TGAParams } from "./tga"
import { ifLoggerKeeper } from './base';
import { LocalDate } from '../lib/Time';
import { LogKitLogger, LogKitParams } from './logkit';
import { createHash } from 'crypto';
import { TGALoggerNet } from './tganet';
export class LoggerMoudle<T> {
    // 这里导出日志

    private keeper: ifLoggerKeeper[] = [];
    private apiTimeout: number = 3000;
    constructor() {

    }

    static types = {
        taobao: "taobao",
        logkit: "logkit",
        tga: "tga",
        tganet: "tganet"
    }

    /**
     * 初始化日志模块 支持多个平台同时存在
     * @param plts taobao,logkit,tga
     * @param config 配置信息
     */
    async init(plts: string | string[], config: { [x: string]: any } | ALiSLSParams | TGAParams | LogKitParams) {
        if (typeof plts == "string") {
            plts = plts.split(',')
        }

        for (let i = 0; i < plts.length; i++) {
            let plt = plts[i]
            switch (plt) {
                case "taobao":
                    this.keeper.push(new TaoBaoLogger(config as ALiSLSParams))
                    break;
                case "logkit":
                    this.keeper.push(new LogKitLogger(config as LogKitParams))
                    break;
                case "tganet":
                    this.keeper.push(new TGALoggerNet(config as TGAParams))
                    break;
                case "tga":
                    this.keeper.push(new TGALogger(config as TGAParams))
                    break;
                default:
            }
        }

        this.baseReqHead = createHash("md5").update(plts.join(",") + Date.now()).digest("hex")

        for (let i = 0; i < this.keeper.length; i++) {
            await this.keeper[i].init();
        }
        return true;
    }

    /**
     * 设置默认超时时间
     * @param apiTimeout 
     */
    setApiTimeOut(apiTimeout: number) {
        this.apiTimeout = apiTimeout;
    }

    protected logEvent(uid: string, event_name: string, obj: Object, support_plts?: string[]) {
        this.keeper.forEach(v => {
            // 考虑某些日志可能只需要记录到特定的平台
            if (support_plts && support_plts.indexOf(v.name) < 0) return
            v.logEvent(uid, event_name, obj)
        })
    }

    protected logStatic(uid: string, eventType: string, obj: Object, support_plts?: string[]) {
        this.keeper.forEach(v => {
            // 考虑某些日志可能只需要记录到特定的平台
            if (support_plts && support_plts.indexOf(v.name) < 0) return
            v.logStatic(uid, eventType, obj)
        })
    }

    protected logAPI(api: string, method: string, uid: string, succ: boolean, consumeTime: number, reqID: string, param: { [x: string]: any } | string, response: { [x: string]: any } | string, support_plts?: string[]) {
        this.keeper.forEach(v => {
            // 考虑某些日志可能只需要记录到特定的平台
            if (support_plts && support_plts.indexOf(v.name) < 0) return

            if (typeof param != "string") {
                param = JSON.stringify(param)
            }

            if (typeof response != "string") {
                response = JSON.stringify(response)
            }

            v.logApi(api, method, uid, succ, consumeTime, reqID, param, response)
        })
    }

    // 这里实现一个api的记录过程，需要设置一个api的超时事件
    protected genReqID: number = 0;
    protected baseReqHead: string = '';
    protected apiMaps: Map<string, {
        'URI': string,
        'method': string,
        'uid': string,
        'param': any,
        'begin_time': number, // 开始时间
        'timoutHandle': number,// 超时句柄
    }> = new Map()
    /**
     * api请求开始
     * @param URI 请求的URL或者URI
     * @param method 请求的方法 
     * @param uid 用户id
     * @param param 携带的参数
     * @param reqID 请求id,如果没有的话会自动生成一个
     * @param timeOut 请求的超时市场 默认是3000
     */
    apiBegin(URI: string, method: string, uid: string, param?: { [x: string]: any }, reqID?: string, timeOut?: number) {
        reqID = reqID || createHash("md5").update(this.baseReqHead + (this.genReqID++)).digest("hex")

        // 这里设置一个超时时间
        let t = setTimeout(this.apiEnd.bind(this, reqID), timeOut || this.apiTimeout) as any
        let s = {
            URI: URI,
            method: method,
            uid: (uid || "0").toString(),
            param: param || {},
            begin_time: Date.now(),
            timoutHandle: t
        }

        this.apiMaps.set(reqID, s)
        return reqID;
    }

    /**
     * 收到 api 回值信息
     * @param reqID 请求id
     * @param succ 是否成功
     * @param response 回值内容
     */
    apiEnd(reqID: string, succ?: boolean, response?: any) {
        let bInfo = this.apiMaps.get(reqID);
        if (!bInfo) return;
        this.apiMaps.delete(reqID)
        clearTimeout(bInfo.timoutHandle)
        let cstime = Date.now() - bInfo.begin_time;
        this.logAPI(bInfo.URI, bInfo.method, bInfo.uid, succ || false, cstime, reqID, bInfo.param, response || { code: 408 })
    }

    //-------------------------------------------------------------------------------//
    /**
     * 这是一个模板例子，不要使用
     * 玩家注册的时候，发送一份基本数据
     */
    private __on_register__(roleID: string, source: string, scene: string) {
        let outList: string[] = [];

        let outParam = {
            'sSource': source,
            'sScene': scene
        };

        let ot = this.createLog(roleID, outList, outParam);
        this.logStatic(roleID, 'user_set', ot);
    }

    //------------------------------------------//
    /**
     * 这是一个模板例子，不要使用
     * 用户日志代理接口
     */
    private __onLogin__(roleID: string | string, event_name: string, log: any) {
        // let list = ['sType', 'sSubType', 'sItemId', 'iCount', 'sReason', 'sSubinfo'];
        let param: any = {}

        for (let key in log) {
            if (log[key] == undefined) continue;
            param[key] = (log[key] || "").toString()
        }

        let list = Object.keys(param);
        this.logEvent(roleID, event_name, this.createLog(undefined, list, param));
    }


    //-------------------------------------------------------------------------------//

    /**
     * 有需要的话可以重写这个结构
     * @param role 
     * @param arrayList 
     * @param outParam 
     */
    protected createLog(role: string | T | undefined, arrayList: Array<string> = [], outParam: { [key: string]: string | number } = {}): Object {
        // 有几个是必须要有的添加一下
        let needslist: string[] = ['record_time'];
        for (let i = 0; i < needslist.length; i++) {
            if (arrayList.indexOf(needslist[i]) < 0) {
                arrayList.push(needslist[i]);
            }
        }

        // 生成日志的通用接口
        let outLog: { [key: string]: number | string } = {}

        let extList: string[] = [];

        for (let key in arrayList) {
            let sKey = arrayList[key];
            switch (sKey) {
                case 'record_time': outLog[sKey] = LocalDate.formateString(); break;
                default:
                    if (outParam.hasOwnProperty(sKey)) {
                        outLog[sKey] = outParam[sKey];
                    }
                    else {
                        extList.push(sKey);
                    }
                    break;
            }
        }

        return outLog;
    }
}